package cn.itcast.web.controller;

import cn.itcast.domain.system.Module;
import cn.itcast.domain.system.User;
import cn.itcast.service.system.ModuleService;
import cn.itcast.service.system.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
public class LoginController extends BaseController {

    @Autowired
    private UserService userService;

    @Autowired
    private ModuleService moduleService;


    /*
          url: /logout.do
          参数： 没有
          作用： 退出登录
          返回值： 登陆页面
       */
    @RequestMapping("/logout")
    public String logout(){
        //1. 先使用shiro的方法销毁shiro的登录成功标记
        Subject subject = SecurityUtils.getSubject();
        subject.logout(); //销毁shiro在session的标记，然后你才能摧毁session

        ///退出登录的本质就是销毁session的登录成功标记
        session.invalidate(); //直接把整个session销毁
        //如果request域没有存储数据，我们可以使用请求重定向， 如果request域存储了数据，我们一定要使用请求转发。
        return "redirect:/login.jsp";
    }



//    /*
//       该方法的作用：就是处理index.jsp发出请求要调整到后台主页的需求。
//       url: /login.do
//       参数：email 邮箱，  password 密码
//       返回： 登陆成功返回后台主页   登陆失败重新返回登陆页面
//    */
//    @RequestMapping("/login")
//    public String login(String email,String password){
//        //1. 判断邮箱与密码是否为空，如果为空跳回登录页面
//        if(StringUtils.isEmpty(email)||StringUtils.isEmpty(password)){
//            request.setAttribute("error","用户名或者密码不能为空");
//            //request域存储数据，我们需要请求转发
//            return "forward:/login.jsp";
//        }
//
//        //2. 根据邮箱(用户名)去查询用户,如果用户对象为空，用户名不存在
//        User user= userService.findByEmail(email);
//        if(user!=null){
//            //3.  如果用户可以查询到，我们就对比密码
//            if(user.getPassword().equals(password)){
//                //登陆成功,登陆成功需要session中存储登陆成功标记
//                session.setAttribute("loginUser",user);
//
//                //一旦登录成功，，马上查询该用户的菜单
//                List<Module> moduleList = moduleService.findModuleByUser(user);
//                //存储到域中  存储到哪个域？ request（）， session，servletContext
//                session.setAttribute("modules",moduleList);
//
//                return "home/main";  //  完整路径： /WEB-INF/pages/home/main.jsp
//            }else{
//                //不存在该用户名
//                request.setAttribute("error","密码错误");
//                return "forward:/login.jsp";
//            }
//        }else{
//            //不存在该用户名
//            request.setAttribute("error","用户名不存在");
//            return "forward:/login.jsp";
//        }
//
//    }


    /*
          该方法的作用：就是处理index.jsp发出请求要调整到后台主页的需求。
          url: /login.do
          参数：email 邮箱，  password 密码
          返回： 登陆成功返回后台主页   登陆失败重新返回登陆页面
       */
    @RequestMapping("/login")  //现在登陆的逻辑是我们自己的代码去实现登陆，但是shiro不认，你必须使用shiro方法去登陆，
    // shiro才认可这次登陆
    public String login(String email,String password){
        //1. 判断邮箱与密码是否为空，如果两者有一位空都需要返回login.jsp 提示用户
        if(StringUtils.isEmpty(email)||StringUtils.isEmpty(password)){
            //把数据存储到域中，如果要从域中取出数据，我们需要使用使用请求转发。
            request.setAttribute("error","用户名或者密码不能为空");
            return "forward:/login.jsp"; // 是不会经过视图解析器的。
        }

        //====================输入数据、密码不为空时=========================
        try {
            //1. 获取到subject对象
            Subject subject = SecurityUtils.getSubject();

            //2. 把用户输入的邮箱与密码封装成一个Token
            UsernamePasswordToken token = new UsernamePasswordToken(email,password);

            //3. 使用subject发出登录的请求，并且把token传递给Realm
            subject.login(token);

            //4.如果登陆成功，你可以得到一个登陆者用户对象
            User loginUser = (User) subject.getPrincipal();

            //其实shiro登陆成功后，shiro也会在session中做很多的登录成功的标记，这个过程不需要你们参与
            //5. 登陆成功后你要完成事情。

            //这里保存User对象到session中，这里不是做登陆成功的标记，因为登陆成功的标记shiro自己去完成了， 我们这里存储只是为了页面上数据显示
            session.setAttribute("loginUser",loginUser);

            //查找用户拥有的权限
            List<Module> moduleList = moduleService.findModuleByUser(loginUser);
            //菜单大家觉得放在哪个域比较好呢？ request  ， session域
            //由于菜单需要被多次点击，每点击一次就会出现一个request对象，所以放入到request域中不合适
            session.setAttribute("modules",moduleList);

            //返回到后台首页
            return "home/main";

        } catch (UnknownAccountException e) {
            //如果接收到该异常，那么则代表没有该用户名存在。
            request.setAttribute("error","用户名不存在");
            return "forward:/login.jsp";
        }catch (IncorrectCredentialsException e){
            //如果接到该异常就是代表密码错误
            request.setAttribute("error","密码错误");
            return "forward:/login.jsp";
        }

    }


    @RequestMapping("/home")
    public String home(){
        return "home/home";
    }
}
